package com.ruoyi.iot.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


/**
 * 日期工具类，提供各种常用的日期处理方法
 * Created by Andy.Yang on 2017/3/20.
 */
public class DateUtils
{
    // 日志记录器
    private final static Logger log = LoggerFactory.getLogger(DateUtils.class);

    private static final String DATE_FORMATE_STRING_A = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_FORMATE_STRING_B = "yyyy-MM-dd";
    private static final String DATE_FORMATE_STRING_C = "yyyy/MM/dd";
    private static final String DATE_FORMATE_STRING_D = "yyyy/MM/dd HH:mm:ss";
    private static final String DATE_FORMATE_STRING_E = "yyyyMMddHHmmss";


    // 日期格式yyyy-MM-dd
    public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd";
    // 并发日期转化安全变量
    private static ThreadLocal<SimpleDateFormat> threadLocalA = new ThreadLocal<SimpleDateFormat>()
    {
        protected synchronized SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat(DATE_FORMATE_STRING_A);
        }
    };
    private static ThreadLocal<SimpleDateFormat> threadLocalB = new ThreadLocal<SimpleDateFormat>()
    {
        protected synchronized SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat(DATE_FORMATE_STRING_B);
        }
    };
    private static ThreadLocal<SimpleDateFormat> threadLocalC = new ThreadLocal<SimpleDateFormat>()
    {
        protected synchronized SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat(DATE_FORMATE_STRING_C);
        }
    };
    private static ThreadLocal<SimpleDateFormat> threadLocalD = new ThreadLocal<SimpleDateFormat>()
    {
        protected synchronized SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat(DATE_FORMATE_STRING_D);
        }
    };
    private static ThreadLocal<SimpleDateFormat> threadLocalE = new ThreadLocal<SimpleDateFormat>()
    {
        protected synchronized SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat(DATE_FORMATE_STRING_E);
        }
    };

    /**
     * 将字符串按照指定格式转换成日期类型，如果没有指定格式，则使用默认格式yyyy-MM-dd
     *
     * @param dateStr
     *            源字符串
     * @param format
     *            日期格式
     * @return 日期类型数据
     */
    public static Date getDateFromStr(String dateStr, String format)
    {
        log.debug("[getDateFromStr] 日期字符串: dateStr = " + dateStr);
        if (dateStr == null || dateStr.trim().length() == 0) { return null; }

        SimpleDateFormat sdf = null;

        try
        {
            if (format == null || format.trim().length() == 0)
            {
                // 默认格式
                sdf = new SimpleDateFormat(DATE_FORMAT_YYYY_MM_DD);
            }
            else
            {
                // 指定格式
                sdf = new SimpleDateFormat(format);
            }

            return sdf.parse(dateStr);
        }
        catch (ParseException e)
        {
            log.error("[getDateFromStr] 解析日期字符串: dateStr = " + dateStr + "出现异常, 异常信息: " + e.toString());
            return null;
        }
    }

    /**
     * 将日期类型数据按照指定格式转换成字符串，如果没有指定格式，则使用默认格式yyyy-MM-dd
     *
     * @param date
     *            源日期类型数据
     * @param format
     *            日期格式
     * @return 日期字符串
     */
    public static String getStrFromDate(Date date, String format)
    {
        if (date == null) { return ""; }

        SimpleDateFormat sdf = null;

        if (format == null || format.trim().length() == 0)
        {
            // 默认格式
            sdf = new SimpleDateFormat(DATE_FORMAT_YYYY_MM_DD);
        }
        else
        {
            // 指定格式
            sdf = new SimpleDateFormat(format);
        }

        return sdf.format(date);
    }

    /**
     * 获取当天的开始时间，即前一天晚上00:00:00
     * 查询数据库不合适，慎用
     * @return
     */
    public static Date getStartOfDay()
    {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static boolean isWithInYearMonth(Date stopTime, int curYearMonth) {
        Date firstDay = getFirstDayOfMonth(curYearMonth / 100, curYearMonth % 100 - 1);
        Date lastDay = getLastDayOfMonth(curYearMonth/100,curYearMonth%100 -1 );
        return stopTime.compareTo(firstDay) >= 0 && stopTime.compareTo(lastDay) <=0 ;
    }


    /**
     * 获取指定日期后几天的日期
     *
     * @param d
     * @param day
     * @return
     */
    public static Date getDateAfter(Date d, int day)
    {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.add(Calendar.DAY_OF_MONTH, day);
        return now.getTime();
    }

    /**
     * 获取指定日期,之前的多少小时数据
     * @param d
     * @param hours
     * @return
     */
    public static Date getHourAfter(Date d, int hours)
    {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.add(Calendar.HOUR, hours);
        return now.getTime();
    }

    /**
     * 获取指定日期,之前的多少分钟数据
     * @param d
     * @param minutes
     * @return
     */
    public static Date getMinuteAfter( Date d, int minutes )
    {
        Calendar now = Calendar.getInstance();
        now.setTime( d );
        now.add( Calendar.MINUTE, minutes );
        return now.getTime();
    }

    /**
     * 获取指定日期,之前的多少秒数据
     * @param d
     * @param minutes
     * @return
     */
    public static Date getSecondsAfter( Date d, int minutes )
    {
        Calendar now = Calendar.getInstance();
        now.setTime( d );
        now.add( Calendar.SECOND, minutes );
        return now.getTime();
    }

    /**
     * 获取当天的结束时间，即当天晚上23:59:59
     *
     * @return
     */
    public static Date getEndOfDay()
    {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);

        return calendar.getTime();
    }

    /**
     * 由整形值构建时间
     * @param year  2019 年为 19
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    public static Date getDateTime( int year, int month, int day, int hour, int minute, int second )
    {
        Calendar cal = Calendar.getInstance();
        year = cal.get(Calendar.YEAR) / 100 * 100 + year;
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, day );
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }


    /**
     * 查询某年某月的最后一天,注：月份是从0开始的
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfMonth(int year, int month)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    /**
     * 查询某年某月的第一天,注：月份是从0开始的
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getFirstDayOfMonth(int year, int month)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    public static Date getFirstDateOfMonthFee(int year, int month)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);

        cal.set(Calendar.DAY_OF_MONTH, 28);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.add(Calendar.MONTH, -1);
        return cal.getTime();
    }

    public static Date getLastDateOfMonthFee(int year, int month)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);

        cal.set(Calendar.DAY_OF_MONTH, 27);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);

        return cal.getTime();
    }

    /**
     * 查询当前日期所处月份的第一天,注：月份是从0开始的
     *
     * @return
     */
    public static Date getFirstDayOfCurrentMonth()
    {
        Calendar cal = Calendar.getInstance();

        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 查询当前日期所处月份的第一天,注：月份是从0开始的
     *
     * @param date
     * @param daysAfter
     * @return
     */
    public static Date getDaysLaterTime(Date date, int daysAfter)
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH, daysAfter);
        //long oldTimeInMills = date.
        return cal.getTime();
    }
    /**
     * 获取当前的年月, 格式yyyyMM
     *
     * @return 当前的年月
     */
    public static int getCurrentYearMonth()
    {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        return year *100 + (month + 1);
    }
    /**
     * 获取当前的年月, 格式yyyyMM
     *
     * @return 当前的年月
     */
    public static int getNextYearMonth()
    {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        cal.add(Calendar.MONTH, 1);
        int month = cal.get(Calendar.MONTH);
        return year *100 + (month + 1);
    }

    /**
     * 获取下个月的第一天, 格式yyyyMMdd
     *
     * @return 年月日
     */
    public static int getNextYearMonthFirstDay()
    {
        return getNextYearMonth() * 100 + 1;
    }

    /**
     * 获取下个月的第一天, 格式yyyyMMdd
     *
     * @return 年月日
     */
    public static int getNextYearLastDay()
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.YEAR, 1);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.get( Calendar.DAY_OF_MONTH );
        return (year * 100 + (month + 1)) * 100 + day ;
    }

    /**
     * 获取当前的年月日, 格式yyyyMMdd
     *
     * @return 当前的年月日
     */
    public static String getCurrentYearMonthDay()
    {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        month = month + 1;
        int day = cal.get(Calendar.DAY_OF_MONTH);

        String result = year + "";
        if (month < 10)
        {
            result = result + "0" + month;
        }
        else
        {
            result = result + month;
        }

        if (day < 10)
        {
            result = result + "0" + day;
        }
        else
        {
            result = result + day;
        }

        return result;
    }

    /**
     * 获取当前的年月日, 格式yyyyMMddHHmmss
     *
     * @return 当前的年月日
     */
    public static String getCurrentYearMonthDayTime()
    {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int minute = cal.get(Calendar.MINUTE);
        int second = cal.get(Calendar.SECOND);
        month = month + 1;
        int day = cal.get(Calendar.DAY_OF_MONTH);

        String result = year + "";
        if (month < 10)
        {
            result = result + "0" + month;
        }
        else
        {
            result = result + month;
        }

        if (day < 10)
        {
            result = result + "0" + day;
        }
        else
        {
            result = result + day;
        }

        if (hour < 10)
        {
            result = result + "0" + hour;
        }
        else
        {
            result = result + hour;
        }

        if (minute < 10)
        {
            result = result + "0" + minute;
        }
        else
        {
            result = result + minute;
        }

        if (second < 10)
        {
            result = result + "0" + second;
        }
        else
        {
            result = result + second;
        }

        return result;
    }


    /**
     * 将整形格式的年月日转换为带格式的字符串
     *
     * @return 当前的年月日
     */
    public static String getDateStrFromInt(Integer oneDate )
    {
        if ( null == oneDate )
        {
            return "2000-01-01";
        }

        String strDate = String.valueOf( oneDate );
        if ( strDate.length() < 8 )
        {
            return "2000-01-01";
        }
        String result = strDate.substring(0,4) + "-" + strDate.substring(4, 6) + "-"  + strDate.substring(6,8);
        return result;
    }

    /**
     * 将整形格式的年月日时分秒 转换为 带格式的字符串
     *
     * @return 当前的年月日
     */
    public static String getDateStrFromLong(Long oneDate )
    {
        if ( null == oneDate )
        {
            return "2000-01-01 00:00:00";
        }

        String strDate = String.valueOf( oneDate );
        if ( strDate.length() < 14 )
        {
            return "2000-01-01 00:00:00";
        }

        String result = strDate.substring(0,4) + "-" + strDate.substring(4, 6) + "-"  + strDate.substring(6, 8) + " " +
        strDate.substring(8, 10) + ":" + strDate.substring(10, 12) + ":" + strDate.substring(12, 14);
        return result;
    }


    /**
     * 获取当前的年月日, 格式yyyy-MM-dd
     *
     * @return 当前的年月日
     */
    public static String getCurrentYearMonthDayOther()
    {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        month = month + 1;
        int day = cal.get(Calendar.DAY_OF_MONTH);

        String result = year + "-";
        if (month < 10)
        {
            result = result + "0" + month;
        }
        else
        {
            result = result + month;
        }

        if (day < 10)
        {
            result = result + "-0" + day;
        }
        else
        {
            result = result + "-" + day;
        }

        return result;
    }

    /**
     * 获取第一个时间参数与第二个时间参数的时间差, 以天为单位
     *
     * @param firstDay
     *            第一个时间
     * @param secondDay
     *            第二个时间
     * @param dateFormat
     *            时间格式, 默认为yyyy-MM-dd HH:mm:ss
     * @return 时间差, 以天为单位
     */
    public static int getTimeDifference(String firstDay, String secondDay, String dateFormat)
    {
        if (dateFormat == null || dateFormat.trim().length() == 0)
        {
            dateFormat = "yyyy-MM-dd HH:mm:ss";
        }

        DateFormat df = new SimpleDateFormat(dateFormat);

        try
        {
            Date d1 = df.parse(firstDay);
            Date d2 = df.parse(secondDay);
            long diff = d1.getTime() - d2.getTime();
            long days = diff / (1000 * 60 * 60 * 24);

            return (int) days;
        }
        catch (Exception e)
        {
            log.error( e.getMessage() );
            return 0;
        }
    }

    /**
     * 获取第一个时间参数与第二个时间参数的时间差, 以天为单位
     *
     * @param firstDay
     *            第一个时间
     * @param secondDay
     *            第二个时间
     * @param dateFormat
     *            时间格式, 默认为yyyy-MM-dd HH:mm:ss
     * @return 时间差, 以天为单位
     * @throws ParseException
     */
    public static int getTimeDifferenceOther(String firstDay, String secondDay, String dateFormat)
            throws ParseException
    {
        if (dateFormat == null || dateFormat.trim().length() == 0)
        {
            dateFormat = "yyyy-MM-dd HH:mm:ss";
        }
        DateFormat df = new SimpleDateFormat(dateFormat);
        Date d1 = df.parse(firstDay);
        Date d2 = df.parse(secondDay);
        long diff = d1.getTime() - d2.getTime();
        long days = diff / (1000 * 60 * 60 * 24);
        return (int) days;
    }

    /**
     * 自动适配两种格式的日期字符串转换为date对象 A格式 : yyyy-MM-dd HH:mm:ss B格式 : yyyy-MM-dd
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getDateFromStringAdaptTwoPattern(String date) throws ParseException
    {
        try
        {
            return getDateFromString(date, DATE_FORMATE_STRING_A);
        }
        catch (ParseException e)
        {
            try
            {
                return getDateFromString(date, DATE_FORMATE_STRING_B);
            }
            catch (ParseException e1)
            {
                return getDateFromString(date, DATE_FORMATE_STRING_C);
            }
        }
    }

    /**
     * 将格式将日期字符串转换为Date对象
     *
     * @param date
     *            字符串
     * @param pattern
     *            格式如下： yyyyMMddHHmmss yyyy-MM-dd HH:mm:ss yyyy-MM-dd MM/dd/yyyy
     *            HH:mm:ss a yyyy-MM-dd HH:mm:ss a yyyy-MM-dd'T'HH:mm:ss'Z'
     *            yyyy-MM-dd'T'HH:mm:ssZ yyyy-MM-dd'T'HH:mm:ssz
     * @return 日期Date对象
     * @throws ParseException
     * @see Date
     */
    public static Date getDateFromString(String date, String pattern) throws ParseException
    {
        SimpleDateFormat sDateFormat = getDateFormat(pattern);
        return sDateFormat.parse(date);
    }

    /**
     * 根据pattern取得的date formate
     *
     * @param pattern
     * @return
     */
    public static SimpleDateFormat getDateFormat(String pattern)
    {
        if (DATE_FORMATE_STRING_A.equals(pattern))
        {
            return threadLocalA.get();
        }
        else if (DATE_FORMATE_STRING_B.equals(pattern))
        {
            return threadLocalB.get();
        }
        else if (DATE_FORMATE_STRING_C.equals(pattern))
        {
            return threadLocalC.get();
        }
        else if (DATE_FORMATE_STRING_D.equals(pattern))
        {
            return threadLocalD.get();
        }
        else
        {
            return threadLocalE.get();
        }
    }

    /**
     * 获取当前周的周一，每周的第一天为周日，第七天为周六
     *
     * @return
     */
    public static Date getMonday()
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    /**
     * 获取当前周的开始时间，周一的00:00:00
     *
     * @return
     */
    public static Date getWeekStart()
    {
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当前周的周日，每周的第一天为周日，第七天为周六
     *
     * @return
     */
    public static Date getSunday()
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return cal.getTime();
    }

    /**
     * 获取当前周的结束时间，周日的23:59:59
     *
     * @return
     */
    public static Date getWeekEnd()
    {
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }
    public static boolean isMorethan27()
    {
        Calendar cal = Calendar.getInstance();

        return cal.get(Calendar.DAY_OF_MONTH) >=27;
    }

    /**
     * @param time 要转换的毫秒数
     * @return 该毫秒数转换为 * days * hours * minutes * seconds 后的格式
     * @author fy.zhang
     */
    public static String formatDuring(long time)
    {
        String result = "";

        long hours = time / (1000 * 60 * 60);
        long minutes = (time % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (time % (1000 * 60)) / 1000;

        if (hours > 0)
        {
            result += hours + "时";
        }
        if (minutes > 0)
        {
            result += minutes + "分";
        }
        result += seconds + "秒";

        return result;
    }

    /**
     *获取明天
     * @param
     * @author fy.zhang
     */
    public static String getTomorrow(){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
        date=calendar.getTime();   //这个时间就是日期往后推一天的结果
        String reStr = sdf.format(date);
        return reStr;
    }

    /**
     * 加上指定的月份
     * @param
     * @author fy.zhang
     */
    public static String addMonth(int nums ){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        //Date dt=sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MONTH,nums);//日期加nums个月
        Date dt1=rightNow.getTime();
        String reStr = sdf.format(dt1);
        return reStr;
    }

    /**
     * 获取两个时间段内的日期
     * @param dBegin
     * @param dEnd
     * @return
     */
    public static List<Date> findDates(Date dBegin, Date dEnd)
    {
        List<Date> lDate = new ArrayList<Date>();
        lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime()))
        {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(calBegin.getTime());
        }
        return lDate;
    }


    public static void main(String[] args) throws ParseException
    {
        Date one = DateUtils.getDateTime( 19,4,25,10,11,12);
        System.out.println( DateUtils.getStrFromDate( one, DATE_FORMATE_STRING_A ));
        System.out.println( getHourAfter( new Date(), -17 ) );
    }



}
